文章目录
  1. 1. 冷启动出现的时机
  2. 2. 分析手段
  3. 3. 分析结果
  4. 4. 解决办法
  5. 5. 多 dex 优化

应用开发了几个版本,功能越来越多,集成的 sdk 也越来越多,突然发现,在应用冷启动速度很慢,特别在某些手机上,特别是第一次安装的时候。严重的时候从点击图标启动应用,到看到第一个页面,有些时候需要 6、7s,所以就需要优化一下。

这里优化的是优化冷启动需要的时间,android 应用启动方面的讲解可以参考下我以前写的2篇文章中相关的章节: Android Broadcast 分析——发送、处理Android Binder 分析——普通服务 Binder 对象的传递

冷启动出现的时机

这里解释一下,android 上所谓的冷启动,在技术上是指:应用 Application 不存在的情况下,打开应用需要启动 Application。从用户的角度来说,在4种情况下会出现冷启动:

  1. 第一次安装
  2. 升级应用
  3. 切换到后台,一段时间后(不固定)
  4. 应用某种原因崩溃

分析手段

虽然说,从点击图标,到看到一个页面的时间,人为上可以感官到,但是作为优化性能的分析,还是有一些数值统计会更加直观。android 从 4.4 开始,activity manager(am)会统计 activity 从启动到显示的时间。这里就可以通过统计应用的第一个页面(通常是 Splash 闪屏页)的显示时间,从而评估应用启动的时间。

am 的打印为类似下面这些:

ActivityManager: Displayed com.kk.dict/.activity.SplashActivity: +354ms

这个是在 ActivityRecord 中的 full draw report 函数中打印的 log(具体的源码这里不分析了)。但是注意,这个统计会受到一些场景的影响,例如说,你在启动的闪屏页中又启动的其他不可见的 activity,这个统计有些时候就不会显示(例如说,我们的应用在 Application 中会启动一个不可见空白的 activity 来提供统计日活数据)。所以在调试的过程中,可以暂时先把这些 activity 关掉(后面发现这种 activity 对启动速度影响不大)。

还有一种最简单的手段就是自己统计时间,通过 log 打印,但是由于应用层缺乏 activity 完全显示的回调,所以可以2种方法结合来调试。

分析结果

通过 am 的打印,和自己的 log 打印,发现我们的应用,在下面几个方面存在大量耗时:

  1. Application 中初始化的一些第三方 sdk:例如 友盟推送,bugly 统计,tusdk 等。其中 友盟推送 和 bugly 2个加起来,平均差不多耗时 1s
  2. Splash 页面布局不够简洁,其中还有一开始就启动了异步线程就初始化一些数据库
  3. 第一次安装时,Application 通过添加系统同步框架的帐号,导致系统 ACCOUNT CHANGE 广播,导致大量第三方进程启动,严重拖慢系统性能,导致自己的应用初始化缓慢

解决办法

根据上面的分析,逐条给出解决办法:

1. 这个可以把初始化的第三方 sdk 区分一下(区分是否重型,可以通过自己的 log 统计初始化时间):

(1). 一些初始化快,但是马上就要用到的,例如说: imageloader,volley 等,可以直接放在 Application 的 onCreate 中初始化。

(2). 一些重新的 sdk,但是又不是马上就要用到的,例如说 tusdk(图像处理,不进入图片拾取页面不会调用),可以采用懒加载的方法,稍微封装一下,在使用的界面再初始化

(3). 一些重型的 sdk,在后台使用的,例如说一些推送类的 sdk,可以在 Application 的 onCreate 中,使用一个 Handler 延迟一段时间再初始化。例如留 1s 给闪屏页先展示出来

2. 简洁闪屏页的布局。如果说确实需要复杂布局的,可以优化固定一个简单的样式,例如一个 ImageView 展示一个 log,配上背景色,让 UI 尽快渲染出来。如果闪屏页还需要开线程去加载数据,同样也是利用 Handler 延迟个 300ms 左右再去加载(不要以为异步线程就不会影响 UI),先留时间让 UI 渲染。

3. 这个最坑了,结合之前的一篇工作笔记,我们的应用利用了 android 的同步框架来保活。但是这个手段,却导致一次安装的时候大量第三方应用的进程启动,严重拖慢系统性能,从而导致自己的应用启动缓慢。这个以前是放在 Application 中初始化的,可以放到闪屏页的延迟 Handler 中初始化。

经过上面的优化后,应用的启动速度已经很快了(基本上看到闪屏页在 1s 以内)。但是还是能看到启动的闪屏页面黑屏。这个黑屏是 activity 的 window background。这个可以通过设置透明的 activity 背景解决:

1
2
3
4
<style name="SplashTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
<item name="android:windowDisablePreview">true</item>
</style>

但是不要以为光光设置透明背景能解决启动速度慢的问题。关键在于 Application onCreate 要快,第一个页面的渲染速度要快才行,不然速度慢的话,就算设置了透明背景,体验会更差的(用户看不到黑屏或者白屏,并且长时间没任何反应,效果更差)。

多 dex 优化

当 app 方法数太多的时候,需要拆分多个 dex 文件,这个会对应用启动速度有一定的影响。但是我们的应用大多数还是一个 dex,所以这里没深入研究这方面。facebook 开源了一个 redex(主要目的是通过优化 apk 字节码来减少 apk 体积的),其中有一项是 Interdex ,通过让更多启动需要的类集中在主 dex 来提升多 dex 的启动速度。具体分析可以常见这里: Redex 初探与 Interdex:Andorid 冷启动优化

文章目录
  1. 1. 冷启动出现的时机
  2. 2. 分析手段
  3. 3. 分析结果
  4. 4. 解决办法
  5. 5. 多 dex 优化